#include "usart.h"

UART_HandleTypeDef UART1_Handler;						// UART句柄

// 串口1中断服务程序，注意读取USARTx->SR能避免莫名其妙的错误
u8 USART1_RX_BUF[USART1_REC_LEN];		// 接收缓冲，最大USART1_REC_LEN个字节，末字节为换行符
/***********************************
* 接收状态：
* bit15：接收完成标志
* bit14：接收到0x0d
* bit13~0：接收到的有效字节数目
***********************************/
u16 USART1_RX_STA;										// 接收状态标记
u8 aRxBuffer[RXBUFFERSIZE];						// HAL库USART接收Buffer


/******************************
* 重定义fputc函数
******************************/
int fputc(int ch, FILE *f)
{
	while((USART1->SR & 0x40) == 0); // 循环发送，直到发送完毕
	USART1->DR = (u8)ch;
	return ch;
}

/***************************
* 初始化IO串口1
* bound：波特率
***************************/
void USART1_Init(u32 bound)
{
	// UART初始化设置
	UART1_Handler.Instance = USART1;										// USART1
	UART1_Handler.Init.BaudRate = bound;								// 波特率
	UART1_Handler.Init.WordLength = UART_WORDLENGTH_8B;	// 字长为8位数据格式
	UART1_Handler.Init.StopBits = UART_STOPBITS_1;			// 一个停止位
	UART1_Handler.Init.Parity = UART_PARITY_NONE;				// 无奇偶校验位
	UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE;	// 无硬件流控
	UART1_Handler.Init.Mode = UART_MODE_TX_RX;					// 收发模式
	HAL_UART_Init(&UART1_Handler);											// HAL_UART_Init()会使用UART1
	
	// 不使用HAL库中HAL_UART_Receive_IT函数，使能接收中断函数
	//__HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_RXNE);
	
	HAL_UART_Receive_IT(&UART1_Handler,(u8*)aRxBuffer, RXBUFFERSIZE); // 该函数会开启接收中断：标志位UART_IT_RXNE，
																																		// 并设置接收缓冲，以及接收缓冲接收最大数据量
}

/**********************************************
* UART底层初始化，时钟使能，引脚配置，中断配置
* 该函数会被HAL_UART_Init()调用
* huart：串口句柄
**********************************************/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
	// GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	
	if(huart->Instance == USART1) // 串口1，进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();										// 使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();									// 使能USART1时钟
				
		GPIO_InitStructure.Pin = GPIO_PIN_9;						// PA9
		GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;			// 复用推挽输出
		GPIO_InitStructure.Pull = GPIO_PULLUP;					// 上拉
		GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;// 高速
		HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);			// 初始化PA9
		
		GPIO_InitStructure.Pin = GPIO_PIN_10;						// PA10
		GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;		// 模式要设置为复用输入模式
		HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);			// 初始化PA10
		
		HAL_NVIC_EnableIRQ(USART1_IRQn);								// 使能USART1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);					// 抢占优先级3，子优先级3，即最低中断优先级
		
	}
}

/****************************
* 中断数据接收
****************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART1) // 串口1
	{
		if((USART1_RX_STA & 0x8000) == 0) // 接收未完成
		{
			if(USART1_RX_STA&4000) // 接收到0x0d
			{
				if(aRxBuffer[0] != 0x0a) USART1_RX_STA=0; // 接收错误，重新开始
				else USART1_RX_STA |= 0x8000;							// 接收完成了
			}
			else // 还没接收到0x0d
			{
				if(aRxBuffer[0] == 0x0d) USART1_RX_STA |= 0x4000;
				else
				{
					USART1_RX_BUF[USART1_RX_STA|0x3FFF] = aRxBuffer[0];
					USART1_RX_STA++;
					if(USART1_RX_STA>(USART1_REC_LEN-1))
					{
						USART1_RX_STA=0;				// 接收数据错误，重新开始接收
					}
				}
			}
		}
	}
}


/******************************
* 串口1中断服务程序
******************************/
void USART1_IRQHandler(void)
{
	u32 timeout = 0;
	
	HAL_UART_IRQHandler(&UART1_Handler);					// 调用HAL库中断处理公有函数
	
	timeout = 0;
	while(HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY) // 等待就绪
	{
		timeout++;			// 超时处理
		if(timeout > HAL_MAX_DELAY) break;
	}
	
	timeout = 0;
	while(HAL_UART_Receive_IT(&UART1_Handler, (u8*)aRxBuffer, RXBUFFERSIZE) != HAL_OK) // 一次处理完成后，重新开启中断并设置RxXferCount为1
	{
		timeout++; // 超时处理
		if(timeout > HAL_MAX_DELAY) break;
	}
}

/*
// 采用HAL库处理逻辑效率不高
// 直接把中断控制逻辑写在中断服务函数内部了
void USART1_IRQHandler(void)
{
	u8 Res;
	if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!= RESET)) // 接收中断（接收到的数据必须 是0x0d 0x0a结尾
	{
		HAL_UART_Receive(&UART1_Handler,&Res,1,1000);
		if((USART1_RX_STA & 0x8000) == 0) // 接收未完成
		{
			if(USART1_RX_STA & 0x4000) // 接收到0x0d
			{
				if(Res !=  0x0a) USART1_RX_STA = 0; //接收错误，重新开始
				else USART1_RX_STA |= 0x8000;				// 接收完成
			}
			else // 还没收到0x0d
			{
				if(Res == 0x0d) USART1_RX_STA |= 0x4000;
				else
				{
					USART1_RX_BUF[USART1_RX_STA&0x3FFF]=Res;
					USART1_RX_STA++;
					if(USART1_RX_STA>(USART1_REC_LEN-1)) USART1_RX_STA = 0; // 接收数据错误，重新开始接收
				}
			}
		}
	}
	HAL_UART_IRQHandler(&UART1_Handler);
}

*/

///////////////////////////////////////////////////////
/************* 如果不使用中断函数处理，由于HAL处理
* 逻辑比较多，因此直接写效率比较高
******************************************************/
/*void USART1_IRQHandler(void)
{
	u8 Res;
	
	if(__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_RXNE) != RESET) // 接收中断（接收的数据必须是0x0d 0x0a结尾
	{
		HAL_UART_Receive(&UART1_Handler, &Res, 1, 1000);
		if((USART1_RX_STA & 0x8000) == 0) // 接收未完成
		{
			if(USART1_RX_STA & 0x4000) // 收到0x0a
			{
				if(Res != 0x0d) USART1_RX_STA = 0; // 接收错误，重新开始
				else USART1_RX_STA |= 0x8000; // 接收完成
			}
			else // 还没收到0x0d
			{
				if(Res == 0x0d) USART1_RX_STA |= 0x4000;
				else
				{
					USART1_RX_BUF[USART1_RX_STA & 0x3FFF] = Res;
					USART1_RX_STA++;
					if(USART1_RX_STA>(USART1_REC_LEN-1)) USART1_RX_STA = 0; // 接收错误，重新开始接收
				}
			}
		}
	}
	HAL_UART_IRQHandler(&UART1_Handler);
}
*/